 // CHECK: [[# FILENUM:]] "{{.*}}/HelloWorld.c"
#include "common.h"
int printf(const char *, ...);
struct a {
  char b;
};
struct c {
  struct a b;
  long d;
} f;
union unionTestA {
  char b;
};
union unionTestB {
  union unionTestA b;
  long d;
} x;

struct B {
  char a;
  char b;
  char c;
  char d;
  double x;
  struct a A;
  int e;
  int f;
};

struct D {
  uint32_t a : 24;
  uint16_t : 4;
  int8_t b : 1;
  uint64_t : 0;
  uint8_t c : 1;
};

typedef struct empty {} empty;
#pragma pack(1)
struct Foo {
  empty v1;
  double v2;
  unsigned int v3:31;
};
#pragma pack(1)
struct Foo1 {
  int8_t v2;
  uint32_t v3:31;
};

void test1() {
  //CHECK: intrinsiccall C_memset (addrof ptr %foo_{{.*}}, constval i32 0, constval u64 12)
  //CHECK: dassign %foo_{{.*}} 2 (cvt f64 i32 (constval i32 1))
  //CHECK: dassign %foo_{{.*}} 3 (constval u32 1)
  struct Foo foo = {.v1 = {}, .v2 = 1, .v3 = 1};
  printMemory(&foo, sizeof(struct Foo), __LINE__);
}

void test2() {
  //CHECK: intrinsiccall C_memset (addrof ptr %foo_{{.*}}, constval i32 0, constval u64 12)
  //CHECK: dassign %foo_{{.*}} 3 (constval u32 0x40000000)
  struct Foo foo = {.v3 = (1LL<<30)};
  printMemory(&foo, sizeof(struct Foo), __LINE__);
}

void test3() {
  //CHECK: LOC [[# FILENUM]] [[# @LINE + 4 ]]
  //CHECK-NOT: intrinsiccall C_memset
  //CHECK: dassign %foo_{{.*}} 1 (constval i8 1)
  //CHECK: dassign %foo_{{.*}} 2 (constval u32 1)
  struct Foo1 foo = {.v2 = 1, .v3 = 1};
  printMemory(&foo, sizeof(struct Foo1), __LINE__);
}

short e;
int main(int argc, char **argv) {
  char g[1] = {};
  //CHECK: intrinsiccall C_memset (addrof ptr %h_{{.*}}, constval i32 0, constval u64 64)
  //CHECK: iassign <* <$c>> 3 (
  //CHECK:   array 1 ptr <* <[2] <$c>>> (
  //CHECK:     array 1 ptr <* <[2][2] <$c>>> (addrof ptr %h_{{.*}}, constval i32 1),
  //CHECK:     constval i32 1),
  //CHECK:   constval i64 1)
  struct c h[2][2] = {{{}}, {{}, {{}, 1}}};
  f = h[1][1];
  printf("%d\n", f.d);
  //CHECK: intrinsiccall C_memset (addrof ptr %j_{{.*}}, constval i32 0, constval u64 16)
  union unionTestB j[2] = {{}, {1}};
  x = j[1];
  printf("%d\n", x.d);
  //CHECK: intrinsiccall C_memset (addrof ptr %arr_{{.*}}, constval i32 0, constval u64 16)
  int arr[2][2] = {{}, {1, {3, 2}}};
  printf("%d %d %d %d\n", arr[0][0], arr[0][1], arr[1][0], arr[1][1]);
  for (; e != 9; ++e)
    if (f.b.b)
      break;
  printf("%d\n", e);
  //CHECK: intrinsiccall C_memset (addrof ptr %d_{{.*}}, constval i32 0, constval u64
  //CHECK: dassign %d_{{.*}} 1 (constval u32 1)
  //CHECK: dassign %d_{{.*}} 3 (constval i8 2)
  //CEHCK: dassign %d_{{.*}} 5 (constval u8 3)
  struct D d = {1, 2, 3, 4, 5};
  printf("%d %d %d\n", d.a, d.b, d.c);

  runTest(test1);
  runTest(test2);
  //CHECK: dassign %un_{{.*}} 1 (constval i32 1)
  //CHECK: intrinsiccall C_memset (
  //CHECK:   add ptr (addrof ptr %un_{{.*}}, constval u64 4),
  //CHECK:   constval i32 0,
  //CHECK:   constval u64 8)
  union {
    int x;
    struct {
      int a;
      int e;
    };
    int;
    int b;
    struct {
      int c;
      long d;
    };
  } un = {1,2,3,4,5,7};
  //CHECK: intrinsiccall C_memset (addrof ptr %un1_{{.*}}, constval i32 0, constval u64 12)
  //CHECK: dassign %un1_{{.*}} 1 (constval i32 1)
  union {
    int x;
    struct {
      int a;
      int e;
    };
    int : 4;
    int b;
    struct {
      int c;
      long d;
    };
  } un1 = {1,2,3,4,5,7};
  //CHECK: LOC [[# FILENUM]] [[# @LINE + 10 ]]
  //CHECK-NOT: intrinsiccall C_memset
  //CHECK:  dassign %un2_{{.*}} 1 (constval i32 1)
  union {
    int x;
    struct {
      int a;
      int e;
    };
    int b;
  } un2 = {1,2,3};
  //CHECK: intrinsiccall C_memset (addrof ptr %un3_{{.*}}, constval i32 0, constval u64 8)
  union {
    int x;
    struct {
      int a;
      int e;
    };
    int b;
  } un3 = {};
  //CHECK-NOT: intrinsiccall C_memset
  //CHECK: dassign %un4_{{.*}} 2 (constval i32 2)
  union {
    empty v1;
    int b;
  } un4 = {.v1={}, .b=2};

  //CHECK: intrinsiccall C_memset (addrof ptr %str_{{.*}}, constval i32 0, constval u64 12)
  //CHECK: intrinsiccall C_memcpy (
  //CHECK: array 1 ptr <* <[3][4] u8>> (addrof ptr %str_{{.*}}, constval i32 0),
  //CHECK: conststr ptr "test",
  //CHECK: constval u64 4)
  char str[3][4] = {"test"};

  //CHECK: LOC [[# FILENUM]] [[# @LINE + 3 ]]
  //CHECK-NOT: intrinsiccall C_memset
  int a[5] = {
    1, 3, 5, 7, [0] = 8, 6, 4, 2, 1
  };
  //CHECK: intrinsiccall C_memcpy (
  //CHECK:   array 1 ptr <* <[4] u8>> (addrof ptr %strstr_{{.*}}, constval i32 0),
  //CHECK:   conststr ptr "123",
  //CHECK:   constval u64 3)
  //CHECK: intrinsiccall C_memset (
  //CHECK:  add ptr (
  //CHECK:  array 1 ptr <* <[4] u8>> (addrof ptr %strstr_{{.*}}, constval i32 0),
  //CHECK:  constval u64 3)
  //CHECK:  constval i32 0,
  //CHECK:  constval u64 1)
  char strstr[]={"123"};

  //CHECK: intrinsiccall C_memset (addrof ptr %SSS_{{.*}}, constval i32 0, constval u64 5)
  //CHECK: dassign %SSS_{{.*}} 1 (dread i32 %argc)
  struct s{
   int a : 31;
   int : 4;
  } SSS = {argc};

  //CHECK: LOC [[# FILENUM]] [[# @LINE + 11 ]]
  //CHECK-NOT: intrinsiccall C_memset
  //CHECK: dassign %S1_{{.*}} 1 (constval u32 1)
  //CHECK: dassign %S1_{{.*}} 2 (constval i8 2)
  //CHECK: dassign %S1_{{.*}} 3 (constval u8 3)
  struct s1{
    uint32_t a;
    uint16_t;
    int8_t b;
    uint64_t;
    uint8_t c;
  } S1 = {1, 2, 3};
  //CHECK: intrinsiccall C_memset (addrof ptr %S2_{{.*}}, constval i32 0, constval u64 12)
  struct s2{
    uint32_t a;
    struct {
      int b;
      int : 0;
    };
    int c;
  } S2 = {1, 2, 3};
  //CHECK: intrinsiccall C_memset (addrof ptr %S3_{{.*}}, constval i32 0, constval u64 15)
  //CHECK: dassign %S3_{{.*}} 1 (constval u32 1)
  //CHECK: dassign %S3_{{.*}} 2 (constval i64 2)
  //CHECK-NOT: dassign %S3_{{.*}} 3 (constval u16 0)
  struct s3{
   uint32_t a;
   int64_t b;
   uint16_t c;
   int8_t d;
  } S3 = {1, 2, 0};
  //CHECK: dassign %S4_{{.*}} 1 (constval u32 1)
  //CHECK: intrinsiccall C_memset (addrof ptr %S4_{{.*}} 2, constval i32 0, constval u64 16)
  //CHECK: dassign %S4_{{.*}} 4 (constval i8 1)
  struct s4{
    uint32_t a;
    int64_t b;
    uint64_t c;
    int8_t d;
  } S4 = {1, 0, 0, 1};
  //CHECK: intrinsiccall C_memset (addrof ptr %arr1_{{.*}}, constval i32 0, constval u64 20)
  //CHECK: iassign <* i32> 0 (
  //CHECK:   array 1 ptr <* <[5] i32>> (addrof ptr %arr1_{{.*}}, constval i32 0),
  //CHECK:   constval i32 1)
  //CHECK-NOT: array 1 ptr <* <[5] i32>> (addrof ptr %arr1_{{.*}}, constval i32 1),
  //CHECK: iassign <* i32> 0 (
  //CHECK:   array 1 ptr <* <[5] i32>> (addrof ptr %arr1_{{.*}}, constval i32 2),
  //CHECK: constval i32 3)
  int arr1[5] = {1, 0, 3};
  return 0;
}
